from django.utils import simplejson
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
import logging

import glp.util
from glp.library import LabelUtils
from glp.library import Librarian
from glp.library import Reader



# TODO(sdd): should be post, since it has side effects
# TODO(sdd): specify a way for this to only delete some
# TODO(sdd): transactions
# TODO(sdd): remove ' ' after : in labels
# TODO(sdd): Check for invalid labels
class EnqueueTask(webapp.RequestHandler):

    def get(self):
        # checks for illegal values at same time
        task_name = {
            '/admin/library/import-documents': 'import-documents',
            '/admin/library/rebuild-metadata': 'rebuild-metadata',
            '/admin/library/update-metadata': 'update-metadata',
            '/admin/library/rebuild-index': 'rebuild-index'}[self.request.path];
        tasks = []
        if (task_name == 'import-documents'):
            for id in Librarian.ImportableDocuments():
                Librarian.PrepareDocumentImport(id)
                tasks.append(glp.util.EnqueueTask('library', 'import-document', id, 'librarian'))
        if (task_name == 'rebuild-metadata'):
            Librarian.ClearMetadata()
            Librarian.ClearIndex()
            for uri in Librarian.LiveFileURIs(Librarian.GetBucket()):
                tasks.append(glp.util.EnqueueTask('library', 'update-metadata', str(uri), 'librarian'))
        if (task_name == 'update-metadata'):
            if len(self.request.body) == 0:
                gsd_uris = [str(gsd_uri) for gsd_uri in Librarian.LiveFileURIs()]
            else:
                gsd_uris = self.request.body.split('\n')
            for gsd_uri in gsd_uris:
                tasks.append(glp.util.EnqueueTask('library', 'update-metadata', gsd_uri, 'librarian'))
        if (task_name == 'rebuild-index'):
            tasks.append(glp.util.EnqueueTask('library', 'rebuild-index', '', 'librarian'))
        message = ''.join(['%s enqueued.\n' % task for task in tasks])
        glp.util.SimplePage(self.response, message)

class ExecuteTask(webapp.RequestHandler):
    def get(self):
        # checks for illegal values at same time
        task_name = {
            # Should be post when called from site
            '/admin/library/stage-document-metadata': 'stage-metadata' }[self.request.path];
        if (task_name == 'stage-metadata'):
            Librarian.StageMetadata(glp.util.HttpResponsePrinter(self.response))
        logging.info("Finished executing task " + task_name)
    def post(self):
        # checks for illegal values at same time
        task_name = {
            '/tasks/library/stage-document-file': 'stage-file',
            '/tasks/library/import-document' : 'import-document',
            '/tasks/library/update-metadata': 'update-metadata',
            '/tasks/library/rebuild-index': 'rebuild-index',
            '/tasks/library/update-index': 'update-index' }[self.request.path];
        logging.info("Starting to execute task " + task_name)
        printer = glp.util.AppEnginePrinter(self.response)
        if (task_name == 'stage-file'):
            XX
        if (task_name == 'import-document'):
            Librarian.ImportDocument(self.request.body)
        if (task_name == 'update-metadata'):
            Librarian.UpdateMetadata([self.request.body], printer)
        if (task_name == 'rebuild-index'):
            Librarian.ClearIndex()
            ids = [metadata.id for metadata in Reader.LiveMetadata()]
            Librarian.UpdateIndex(ids, printer)
        if (task_name == 'update-index'):
            if len(self.request.body) == 0:
                ids = [metadata.id for metadata in Reader.LiveMetadata()]
            else:
                ids = self.request.body.split('\n');
            Librarian.UpdateIndex(ids, printer)
        logging.info("Finished executing task " + task_name)

class JSONEncoder(simplejson.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, glp.library.document.DocumentMetadata):
            return {
                'id' : obj.id,
                'url' : obj.storage_uri,
                'title' : obj.title,
                'authors' : obj.authors,
                'sources' : obj.sources,
                'description' : obj.description,
                'year' : obj.year,
                'labels' : [(label, LabelUtils.PrettifyLabel(label)) for label in obj.labels]}
        return simplejson.JSONEncoder.default(self, obj)

class Query(webapp.RequestHandler):
    def get(self):
        query = {
            '/admin/library/topics' : 'topics',
            '/admin/library/documents' : 'documents' }[self.request.path];
        labels = self.request.get('q')
        id = self.request.get('id')
        if id == '': id = None
        if labels == None:
            labels = []
        else:
            labels = labels.split()
        if (query == 'topics'):
            response = [(topic_label, LabelUtils.PrettifyLabel(topic_label)) for topic_label in Reader.LabelsTopics(labels)]
        if (query == 'documents'):
            if id != None:
                response = Reader.DocumentMetadata(id)
            else:
                response = db.get(Reader.LabelsDocumentKeys(labels))
        self.response.out.write(simplejson.dumps(response, cls=JSONEncoder))


def main():
    logging.getLogger().setLevel(logging.DEBUG)
    application = webapp.WSGIApplication([
            ('/admin/library/stage-document-file', ExecuteTask),
            ('/admin/library/stage-document-metadata', ExecuteTask),
            ('/admin/library/import-documents', EnqueueTask),
            ('/admin/library/rebuild-metadata', EnqueueTask), # list or all
            ('/admin/library/update-metadata', EnqueueTask), # list or all
            ('/admin/library/rebuild-index', EnqueueTask),

            ('/tasks/library/import-document', ExecuteTask),
            ('/tasks/library/update-metadata', ExecuteTask),
            ('/tasks/library/rebuild-index', ExecuteTask),
            ('/tasks/library/update-index', ExecuteTask),

            ('/admin/library/topics', Query),
            ('/admin/library/documents', Query)

            ], debug=True)
    run_wsgi_app(application)


if __name__ == "__main__":
    main()
